<script setup lang="ts">
import type { AdminModel } from '@/apis/types/admin'
import type { FormInstance } from '@arco-design/web-vue'
import { addAdminApi, updateAdminApi } from '@/apis/modules/admin'
import { Message } from '@arco-design/web-vue'

import { pick } from 'lodash-es'

const emit = defineEmits<{
  (event: 'reload'): void
}>()
const visible = defineModel({ default: false })
const loading = defineModel<boolean>('loading', { default: false })

const record = defineModel<AdminModel>('record', { default: undefined })

const title = computed<string>(
  () => `${record.value?.id ? '编辑' : '添加'}账号`,
)
const isEdit = computed(() => !!record.value?.id)

const formRef = ref<FormInstance>()

type PickAdmin = 'id' | 'password' | 'username' | 'role' | 'status'

const formState = ref<Pick<Required<AdminModel>, PickAdmin>>({
  id: '',
  username: '',
  role: 2,
  password: defaultPassword(),
  status: 1,
})

const rules = computed<Rules>(() => {
  const res: Rules = {
    username: [
      {
        required: true,
        validator(value, callback) {
          const reg = /^\w{4,18}$/
          if (!value) {
            callback('请输入账号')
          } else if (!reg.test(value)) {
            callback('请输入4-18个字符，可包含英文字母、数字、下划线')
          } else {
            callback()
          }
        },
      },
    ],
    role: [{ required: true, message: '请选择角色' }],
    password: [
      {
        required: true,
        message: '请输入密码',
      },
      {
        required: true,
        validator: passwordValidate,
        message: '请输入6-64个字符，可包含英文字母、数字和标点符号（除空格）',
      },
    ],
    status: [{ required: true, message: '请选择状态' }],
  }
  return res
})

async function handleOk() {
  const res = await formRef.value?.validate?.()
  if (!res) {
    const pickFields = record.value?.id
      ? ['id', 'status', 'role']
      : ['username', 'role', 'password', 'status']
    const action = record.value?.id ? updateAdminApi : addAdminApi
    // @ts-ignore
    return action(pick(formState.value, pickFields))
      .then(() => {
        Message.success(record.value?.id ? '修改成功' : '添加成功')
        emit('reload')
        return Promise.resolve(true)
      })
      .catch(async (error: any) => {
        formRef.value?.setFields({
          username: {
            message: error.message,
            status: 'error',
          },
        })
        return Promise.reject(error)
      })
  } else {
    return Promise.reject(new Error('表单验证失败'))
  }
}
function handleOpen() {
  return new Promise((resolve) => {
    formState.value = {
      ...formState.value,
      ...(record.value || {
        id: undefined,
        username: '',
        status: 1,
        role: 2,
        password: defaultPassword(),
      }),
    }
    resolve(true)
  })
}
</script>

<template>
  <resource-dialog
    v-model:visible="visible"
    :width="448"
    :title="title"
    :mask-closable="false"
    :loading="loading"
    :before-ok="handleOk"
    :before-open="handleOpen"
  >
    <a-form
      ref="formRef"
      :model="formState"
      :rules="rules"
      layout="vertical"
    >
      <a-form-item
        asterisk-position="end"
        validate-trigger="change"
        field="username"
        label="账号"
        hide-asterisk
      >
        <a-input
          v-model="formState.username"
          :disabled="isEdit"
          placeholder="请输入账号"
          :max-length="18"
          show-word-limit
        />
      </a-form-item>
      <a-form-item
        v-if="!isEdit"
        asterisk-position="end"
        validate-trigger="input"
        field="password"
        label="密码"
        hide-asterisk
      >
        <a-input-password
          :key="String(visible)"
          v-model="formState.password"
          placeholder="请输入密码"
          :max-length="64"
        />
      </a-form-item>
      <a-form-item
        field="status"
        label="状态"
        validate-trigger="input"
        asterisk-position="end"
        class="mb-0!"
        required
        hide-asterisk
      >
        <a-radio-group
          v-model="formState.status"
          :options="switchStatusOptions"
        />
      </a-form-item>
    </a-form>
  </resource-dialog>
</template>

<style scoped></style>
